import axios, { Axios, AxiosError, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import { ResultEnum } from '@/enums/httpEnum'
import { axiosPre } from '@/settings/httpSetting'
import { includes } from 'lodash'
import { fetchAllowList } from '@/api/axios.config'
import { getLocalStorage } from '@/utils/storage'
import { StorageEnum } from '@/enums/storeageEnum'
import { isPreview, redirectErrorPage, routerTurnByName } from '@/utils/router'
import { ErrorPageNameMap, PageEnum } from '@/enums/pageEnum'
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'

export interface MyResponseType<T> {
  code: ResultEnum
  data: T
  message: string
}

export interface MyRequestInstance extends Axios {
  <T = any>(config: AxiosRequestConfig): Promise<MyResponseType<T>>
}

// 实例
const axiosInstance = axios.create({
  baseURL: `${import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : ''}${axiosPre}`,
  timeout: ResultEnum.TIMEOUT
}) as unknown as MyRequestInstance

// 请求拦截器
axiosInstance.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 白名单校验
    if (includes(fetchAllowList, config.url)) return config
    // 获取token
    const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
    if (!info) {
      routerTurnByName(PageEnum.BASE_LOGIN_NAME)
      return config
    }
    const userInfo = info[SystemStoreEnum.USER_INFO]
    config.headers[userInfo[SystemStoreUserInfoEnum.TOKEN_NAME] || 'token'] =
      userInfo[SystemStoreUserInfoEnum.USER_TOKEN] || ''
    // 重新登录
    return config
  },
  (error: AxiosError) => {
    Promise.reject(error)
  }
)

// 响应拦截器
axiosInstance.interceptors.response.use(
  (res: AxiosResponse) => {
    // 预览页面错误不进行处理
    if (isPreview()) {
      return Promise.resolve(res.data)
    }

    const { code } = res.data as { code: number }

    if (code === undefined || code === null) return Promise.resolve(res.data)

    // 成功
    if (code === ResultEnum.SUCCESS) {
      return Promise.resolve(res.data)
    }

    // 登录过期
    if (code === ResultEnum.TOKEN_OVERDUE) {
      window.$message.error(window.$t('http.token_overdue_message'))
      routerTurnByName(PageEnum.BASE_LOGIN_NAME)
      return Promise.resolve(res.data)
    }

    // 固态错误码重定向
    if (ErrorPageNameMap.get(code)) {
      redirectErrorPage(code)
      return Promise.resolve(res.data)
    }

    // 提示错误
    window.$message.error(window.$t(res.data.msg))

    return Promise.resolve(res.data)
  },
  (error: AxiosError) => {
    const status = error.response?.status
    switch (status) {
      case 401:
        routerTurnByName(PageEnum.BASE_LOGIN_NAME)
        Promise.reject(error)
        break
      default:
        Promise.reject(error)
        break
    }
  }
)

export default axiosInstance
